Popular Searches
Popular Course Categories
Popular Courses

Introduction to Spring Boot Architecture

Introduction to Spring Boot Architecture

Spring Boot Application Development

Introduction to Spring Boot Architecture

Course: Advanced Java Training

Topic: Introduction to Spring Boot Architecture

Course Link: Advanced Java Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction to Spring Boot Architecture

Spring Boot is a Java-based framework built on top of the Spring Framework that simplifies the development of standalone, production-ready applications. It reduces the amount of manual configuration required by providing auto-configuration, starter dependencies, embedded web servers, and production-oriented features.

Spring Boot architecture describes how the application starts, how its components are configured, how HTTP requests are processed, and how business logic communicates with databases and external services.

Traditional Spring applications may require considerable XML or Java-based configuration. Spring Boot simplifies this process by using sensible defaults and configuring components based on the dependencies and settings available in the application.

Spring Boot does not replace the Spring Framework. Instead, it makes Spring applications easier to create, configure, run, test, and deploy.

Example

Suppose you are developing an online shopping application. Spring Boot can help you create REST APIs for products, customers, and orders; connect the application to a database; validate requests; and run the application using an embedded server.

2. Learning Objectives

  • Understand the purpose and architecture of Spring Boot.
  • Learn the major components of a Spring Boot application.
  • Understand the role of the Spring container and dependency injection.
  • Explore auto-configuration and starter dependencies.
  • Understand the responsibilities of controllers, services, repositories, and entities.
  • Learn how HTTP requests travel through a Spring Boot web application.
  • Understand embedded servers, application configuration, and database integration.
  • Learn the basic structure and execution flow of a Spring Boot project.

3. What Is Spring Boot?

Spring Boot is an opinionated extension of the Spring ecosystem designed to reduce repetitive setup work. It provides defaults for common application requirements while allowing developers to customize the configuration whenever necessary.

Key features

  • Auto-configuration: Automatically configures common components based on dependencies and existing application configuration.
  • Starter dependencies: Simplify dependency management by grouping libraries commonly used together.
  • Embedded servers: Allow web applications to run without requiring a separately installed application server.
  • Externalized configuration: Allows settings to be maintained in configuration files, environment variables, or other supported property sources.
  • Production support: Spring Boot Actuator can provide health information, metrics, and other operational endpoints when configured.
  • Spring integration: Supports Spring MVC, Spring Data, Spring Security, and many other Spring projects.
  • Executable packaging: Supports packaging applications as executable JAR files and other deployment formats.

These features allow developers to focus more on business requirements and less on repetitive infrastructure setup.

4. Overview of Spring Boot Architecture

A typical layered Spring Boot web application contains the presentation layer, controller layer, service layer, repository layer, and database. Supporting components such as configuration classes, the Spring container, validation, security, and embedded server infrastructure work alongside these layers.

                Client / Browser
                       |
                       v
                HTTP Request
                       |
                       v
             Embedded Web Server
                       |
                       v
               Spring MVC Layer
                       |
                       v
                  Controller
                       |
                       v
                   Service
                 Business Logic
                       |
                       v
                  Repository
                 Data Access
                       |
                       v
                    Database

Supporting Infrastructure:
Spring Container | Dependency Injection
Auto-Configuration | Security
Validation | Logging | Monitoring

This diagram represents a common application design rather than a mandatory architecture. Small applications may use fewer layers, while larger systems may include additional components such as messaging, caching, API gateways, or separate microservices.

5. Main Components of Spring Boot Architecture

Component Primary Responsibility Common Example
SpringApplication Bootstraps and starts the application SpringApplication.run()
Auto-Configuration Configures suitable components automatically Web MVC and data source configuration
Spring Container Creates and manages application beans Controllers and services
Controller Layer Handles incoming web requests @RestController
Service Layer Implements business logic @Service
Repository Layer Manages data access @Repository or Spring Data repository interfaces
Model / Entity Represents application data Product or Customer entity
Embedded Server Accepts and processes HTTP connections Tomcat for a typical servlet-based application
Configuration Controls application settings application.properties
Actuator Provides operational and monitoring endpoints Health and metrics endpoints

6. Spring Boot Application Entry Point

Every conventional Spring Boot application has a main class that starts the application. This class commonly uses the @SpringBootApplication annotation and invokes SpringApplication.run().

Example: Application.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

How it works

  1. The Java runtime calls the main() method.
  2. SpringApplication.run() bootstraps the Spring Boot application.
  3. Spring prepares the application context and registers configuration and beans.
  4. Auto-configuration evaluates the available dependencies and application settings.
  5. For a web application, the appropriate web infrastructure and embedded server are initialized.
  6. The application becomes ready to handle requests once startup has completed successfully.

7. Understanding @SpringBootApplication

The @SpringBootApplication annotation combines three important annotations that support a typical Spring Boot application.

Annotation Purpose
@SpringBootConfiguration Identifies the class as a source of Spring configuration. It is a specialized form of @Configuration.
@EnableAutoConfiguration Enables Spring Boot's auto-configuration mechanism.
@ComponentScan Scans eligible packages to discover Spring components such as controllers, services, and repositories.

By default, component scanning is based on the package containing the application class and its subpackages. Keeping the main class in a suitable root package helps Spring discover application components.

8. Understanding the Spring Container

The Spring container is responsible for creating and managing application objects known as beans. It also manages their dependencies and lifecycle according to the configured Spring context.

Spring Boot applications commonly use an ApplicationContext, which provides bean management and additional application infrastructure.

What is a Spring bean?

A Spring bean is an object managed by the Spring container. Controllers, services, configuration classes, and other components may become beans through component scanning or explicit bean definitions.

Example

import org.springframework.stereotype.Service;

@Service
public class GreetingService {

    public String getGreeting() {
        return "Welcome to Spring Boot!";
    }
}

The @Service annotation marks the class as a service component that Spring can discover through component scanning. Once registered, it can be injected into other beans.

9. Dependency Injection in Spring Boot

Dependency Injection (DI) is a technique in which an object receives its required dependencies from an external container instead of constructing them itself. Spring manages this process and helps keep application components loosely coupled.

Constructor injection example

import org.springframework.stereotype.Service;

@Service
public class MessageService {

    public String getMessage() {
        return "Hello from the service layer";
    }
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

    private final MessageService messageService;

    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    @GetMapping("/message")
    public String getMessage() {
        return messageService.getMessage();
    }
}

Spring creates the controller bean and supplies the required MessageService bean through the constructor. Constructor injection makes dependencies explicit and supports easier unit testing.

Benefits of dependency injection

  • Reduces tight coupling between components.
  • Improves testability by allowing dependencies to be replaced with test doubles.
  • Centralizes object creation and configuration.
  • Supports cleaner separation of responsibilities.
  • Makes applications easier to extend and maintain.

10. Auto-Configuration in Spring Boot

Auto-configuration is one of Spring Boot's most important features. It attempts to configure commonly needed components based on the libraries present on the classpath, existing beans, and configuration properties.

For example, when web dependencies are present, Spring Boot can configure web application infrastructure. When supported database dependencies and configuration are present, it can configure suitable data access components.

Example

If an application includes Spring MVC dependencies, Spring Boot can configure the relevant MVC infrastructure and an embedded servlet container. Developers can still customize this behavior or provide their own beans when necessary.

How auto-configuration works

  1. The developer adds dependencies to the project.
  2. Spring Boot evaluates the available classes and configuration properties.
  3. Conditional configuration determines which auto-configuration components apply.
  4. Spring registers appropriate beans when the conditions are satisfied.
  5. Custom configuration can replace or override selected defaults when supported.

Auto-configuration is not the same as code generation. Spring Boot configures the running application; it does not normally generate source code or rewrite application files to implement these defaults.

11. Starter Dependencies

Spring Boot starter dependencies simplify project setup by grouping commonly used libraries. Instead of manually selecting every library needed for a common task, developers can add a starter for that application area.

Starter Typical Purpose
spring-boot-starter-web Traditional Spring MVC web applications and REST APIs in many Spring Boot versions
spring-boot-starter-data-jpa JPA-based database access
spring-boot-starter-security Authentication and authorization integration
spring-boot-starter-validation Bean Validation integration
spring-boot-starter-test Common testing libraries and Spring test support
spring-boot-starter-actuator Application monitoring and management features

Starter names and dependency arrangements can vary between Spring Boot generations. Use the dependencies supported by the version selected for the project.

Example Maven dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

The Spring Boot parent or dependency management configuration can manage compatible versions of many related dependencies, reducing the need to specify each version manually.

12. Embedded Web Server

A web application needs a server to receive HTTP requests and return responses. Spring Boot can package an embedded web server with a servlet-based application, allowing the application to start as a standalone process.

Tomcat is a common default for servlet-based Spring Boot web applications. Depending on the dependencies and application type, Jetty or another supported server may be used. Reactive applications typically use a reactive server such as Reactor Netty by default.

Advantages of embedded servers

  • Reduce the need to install and configure a separate application server.
  • Make local development and testing simpler.
  • Support executable JAR deployment workflows.
  • Provide consistent server configuration across development and deployment environments.

A typical servlet-based application often uses port 8080 by default. The port can be changed in the application configuration.

server.port=9090

13. Controller Layer

The controller layer receives incoming web requests and coordinates the application's response. Controllers should generally handle HTTP-specific responsibilities, such as reading request parameters, validating input, and returning response data or a view.

In Spring MVC, @Controller is commonly used for MVC controllers that return views, while @RestController is used for controllers whose return values are written to the response body by default.

Example REST controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "Welcome to the Spring Boot application";
    }
}

When the application receives a GET request for the root path, Spring MVC maps it to the controller method and returns the resulting response body.

14. Service Layer

The service layer contains business logic and coordinates operations required by the application. Keeping business logic outside controllers makes the application easier to maintain and test.

Example

import org.springframework.stereotype.Service;

@Service
public class CalculatorService {

    public int add(int first, int second) {
        return first + second;
    }
}

A controller can call this service to perform the calculation. In a larger system, a service might validate business rules, coordinate multiple repositories, or publish an event after a successful operation.

15. Repository Layer and Database Integration

The repository layer manages persistence and data access. It separates database operations from controllers and business logic.

Spring Data JPA can generate implementations for repository interfaces when the necessary dependencies and configuration are present. An application can also use JDBC or other persistence technologies.

Example entity

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private double price;

    public Product() {
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

Example repository

import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository
        extends JpaRepository<Product, Long> {
}

The repository interface provides common persistence operations, including saving, finding, and deleting records. The entity and repository must be supported by an appropriate database driver and data source configuration.

For Spring Boot 3 and newer, JPA annotations commonly use the jakarta.persistence namespace. Older projects may use javax.persistence, depending on the framework version.

16. Understanding the Model Layer

The model represents the data used by an application. Depending on the architecture, this may include database entities, request and response DTOs, domain objects, or view models.

  • Entity: Represents data persisted in a database.
  • Request DTO: Represents data received from a client.
  • Response DTO: Represents data returned to a client.
  • Domain object: Represents a business concept and its associated rules.

These objects do not have to be the same class. Separating them can help prevent accidental exposure of internal fields and make API contracts easier to maintain.

17. Spring MVC Request Processing Flow

When a client sends an HTTP request to a Spring Boot MVC application, the embedded server accepts the connection and passes the request into the servlet infrastructure. Spring MVC then uses the DispatcherServlet as its central request-processing component.

Request processing steps

  1. The client sends an HTTP request to the application.
  2. The embedded server receives the request.
  3. The servlet infrastructure passes the request to the DispatcherServlet.
  4. Spring MVC identifies a suitable controller method using request mappings.
  5. Request parameters, path variables, or request bodies are converted and bound as required.
  6. Validation and applicable request-processing components run.
  7. The controller invokes the service layer when business logic is required.
  8. The service interacts with repositories or other dependencies.
  9. The result returns through the controller and Spring MVC response handling.
  10. The application sends an HTTP response to the client.
Client
  |
  v
Embedded Server
  |
  v
DispatcherServlet
  |
  v
Handler Mapping
  |
  v
Controller
  |
  v
Service
  |
  v
Repository
  |
  v
Database
  |
  v
Response Handling
  |
  v
Client

For REST APIs, the response may be serialized as JSON. For server-rendered MVC applications, the controller may return a view name that is resolved by a view technology such as Thymeleaf.

18. Application Configuration

Spring Boot supports externalized configuration so that application settings can be changed without modifying business logic. Common settings include the server port, database connection, logging levels, and application-specific properties.

Example application.properties

spring.application.name=product-service
server.port=8080

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

logging.level.root=INFO

The database placeholders above expect the corresponding environment variables to be configured. A suitable JDBC driver and database connection configuration are also required.

For sensitive settings, use environment variables or a secure secrets-management solution instead of committing credentials to source control.

application.properties vs. application.yml

Feature application.properties application.yml
Format Key-value properties Indented YAML structure
Example server.port=8080 server: port: 8080 using YAML indentation
Readability Simple flat configuration Convenient for nested configuration
Purpose External application settings External application settings

19. Profiles and Environment-Specific Configuration

Spring profiles allow different configuration settings to be used for environments such as development, testing, and production. This helps separate environment-specific details from application logic.

Example configuration files

application.properties
application-dev.properties
application-test.properties
application-prod.properties

A development profile can be activated using a configuration property or an environment variable, for example:

spring.profiles.active=dev

Use the activation mechanism appropriate to the deployment environment. Avoid placing production credentials in source-controlled profile files.

20. Exception Handling Architecture

Exception handling helps an application respond consistently when an operation fails. Instead of exposing internal stack traces, a web application should return suitable error responses and log technical details securely.

Spring MVC supports centralized exception handling through @ControllerAdvice and @ExceptionHandler.

Example

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleBadRequest(
            IllegalArgumentException exception) {

        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body("The supplied request is invalid.");
    }
}

This example provides a simple response for a particular exception type. Real applications should define appropriate error DTOs, avoid returning sensitive exception details, and map exceptions to HTTP status codes that accurately represent the failure.

21. Security in Spring Boot Architecture

Spring Security integrates authentication and authorization into Spring applications. Authentication determines who the user is, while authorization determines which resources or operations the user is permitted to access.

Security can be applied through a filter chain and additional application-level checks. The exact configuration depends on whether the application uses sessions, HTTP Basic authentication, OAuth 2.0, JWT-based authentication, or another approach.

Security best practices

  • Require authentication for protected resources.
  • Apply authorization rules based on roles or permissions.
  • Use HTTPS in production environments.
  • Protect secrets and credentials.
  • Validate and safely handle untrusted input.
  • Keep security dependencies updated.
  • Configure CSRF protection appropriately for browser-based session applications.
  • Do not expose management endpoints publicly without proper access controls.

22. Testing in Spring Boot

Testing verifies that individual components and the application as a whole behave as expected. Spring Boot provides testing support through its test starter and integration with common Java testing tools.

Testing Type Purpose Typical Example
Unit testing Tests one component in isolation Test service calculations
Web layer testing Tests controller behavior Verify HTTP status and response content
Repository testing Tests persistence behavior Check entity queries and save operations
Integration testing Tests interactions between components Test a controller and service together
End-to-end testing Checks the complete application flow Submit an order through the API

Tests should cover both successful scenarios and failures, including invalid requests, missing data, authorization errors, and database exceptions.

23. Monitoring and Spring Boot Actuator

Spring Boot Actuator provides operational features that help teams monitor and manage applications. Depending on the dependencies and configuration, it can expose health, metrics, environment, and other management information.

For example, adding the Actuator starter enables supported management endpoints. The health endpoint can be used by monitoring systems to check application health.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Endpoint availability and exposure depend on configuration. Management endpoints should be restricted and secured appropriately because some can reveal operational or environment information.

24. Packaging and Deployment

Spring Boot applications can be packaged and deployed in several ways, including executable JAR files, WAR files for supported deployment scenarios, containers, and cloud platforms.

Build with Maven

mvn clean package

Run an executable JAR

java -jar target/application.jar

The exact JAR name depends on the project's build configuration. Before deployment, configure environment-specific settings, database access, logging, security, and monitoring.

25. Spring Boot Project Structure

A common Maven project layout is shown below. The exact packages and files depend on the application's requirements.

spring-boot-project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── Application.java
│   │   │       ├── controller/
│   │   │       ├── service/
│   │   │       ├── repository/
│   │   │       ├── entity/
│   │   │       ├── dto/
│   │   │       └── config/
│   │   └── resources/
│   │       ├── application.properties
│   │       ├── static/
│   │       └── templates/
│   └── test/
│       └── java/
├── pom.xml
└── README.md

The main application class is commonly placed in the root package so that component scanning can discover classes in its subpackages. Keep controller, service, repository, and configuration responsibilities separate where this improves maintainability.

26. Practical Example: Product API Architecture

Consider a simple product API that returns a product name. The example demonstrates the relationship between the main application class, controller, and service layer.

ProductService.java

package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class ProductService {

    public String getProductName() {
        return "Laptop";
    }
}

ProductController.java

package com.example.demo.controller;

import com.example.demo.service.ProductService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProductController {

    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping("/products/name")
    public String getProductName() {
        return productService.getProductName();
    }
}

Execution flow

  1. Run the application from its main class.
  2. Spring discovers and registers the controller and service beans.
  3. The embedded server starts when the web dependencies and configuration support it.
  4. Send a GET request to /products/name.
  5. Spring MVC maps the request to getProductName().
  6. The controller calls the injected service.
  7. The service returns the product name.
  8. The response body contains Laptop.

This example keeps the architecture simple. A production product API would typically use a repository for persistent data, DTOs, validation, error handling, security, and automated tests.

27. Common Spring Boot Architecture Mistakes

Mistake Impact Recommended Solution
Placing the main class in an unsuitable package Components may not be discovered automatically Use a suitable root package and review component scanning
Putting all logic in controllers Code becomes difficult to test and maintain Move business logic into services
Ignoring dependency compatibility Build or runtime errors may occur Use dependencies compatible with the chosen Spring Boot version
Hardcoding secrets Credentials may be exposed Use environment variables or a secure secret store
Exposing management endpoints without protection Operational data may be disclosed Restrict and secure management access
Skipping automated tests Regressions may reach production Add unit, integration, and web-layer tests
Returning internal exception details Sensitive implementation details may leak Use consistent error responses and secure logging
Using database entities for every API request Internal fields may be exposed or modified unintentionally Use request and response DTOs when appropriate

28. Practical Exercises

Exercise 1: Create a basic Spring Boot application

  • Create a Maven project with Spring Web.
  • Add a main class with @SpringBootApplication.
  • Create a controller that returns a welcome message.
  • Run the application and test the endpoint.

Exercise 2: Implement a layered application

  • Create a controller, service, and repository package.
  • Move business logic from the controller into a service.
  • Use constructor injection for dependencies.
  • Write tests for the service and controller.

Exercise 3: Connect a database

  • Add the appropriate database driver and persistence dependencies.
  • Configure database connection settings securely.
  • Create an entity and repository.
  • Implement create and retrieve operations.
  • Test valid requests and database failure scenarios.

Exercise 4: Prepare for deployment

  • Configure environment-specific properties.
  • Add appropriate validation and exception handling.
  • Enable and secure required Actuator endpoints.
  • Build an executable artifact and run it.
  • Document the deployment and configuration steps.

29. Interview Questions and Answers

Q1. What is Spring Boot?

Answer: Spring Boot simplifies Spring application development through auto-configuration, starter dependencies, embedded servers, and production-oriented features.

Q2. What is Spring Boot architecture?

Answer: It describes how application startup, configuration, request handling, business logic, data access, and supporting infrastructure work together.

Q3. What does @SpringBootApplication do?

Answer: It combines Spring Boot configuration, auto-configuration, and component scanning through three annotations.

Q4. What is auto-configuration?

Answer: It conditionally configures application components based on available dependencies, existing beans, and configuration settings.

Q5. What are Spring Boot starters?

Answer: Starters are dependency descriptors that group commonly used libraries for application tasks such as web development, validation, and database access.

Q6. What is a Spring bean?

Answer: A Spring bean is an object created and managed by the Spring container.

Q7. What is dependency injection?

Answer: Dependency injection supplies an object's required dependencies from an external container instead of having the object create them directly.

Q8. What is the role of DispatcherServlet?

Answer: It is the central servlet in Spring MVC that coordinates request handling by finding appropriate handlers and managing response processing.

Q9. What is the difference between a controller and a service?

Answer: A controller handles web requests and responses, while a service contains business logic and coordinates application operations.

Q10. What is the purpose of the repository layer?

Answer: It separates data-access operations from business logic and provides a consistent way to interact with persistence systems.

Q11. What is an embedded server?

Answer: It is a web server packaged with the application so that the application can run as a standalone process.

Q12. What is Spring Boot Actuator?

Answer: Actuator provides operational features such as health information and metrics through supported management endpoints.

Q13. Why use application.properties?

Answer: It stores externalized settings such as server configuration, database connection properties, and application-specific values.

Q14. Why use constructor injection?

Answer: It makes required dependencies explicit, supports immutable fields, and improves unit testing.

Q15. How does a Spring Boot application process an HTTP request?

Answer: The server receives the request, Spring MVC routes it through the DispatcherServlet to a controller, the controller may invoke services and repositories, and the result is converted into an HTTP response.

30. Quick Revision Checklist

  • Understand the purpose of Spring Boot and its relationship with Spring Framework.
  • Know the three annotations combined by @SpringBootApplication.
  • Understand the Spring container, beans, and dependency injection.
  • Explain auto-configuration and starter dependencies.
  • Identify the responsibilities of controllers, services, repositories, and models.
  • Understand the role of the embedded server and DispatcherServlet.
  • Know how to configure application properties and profiles.
  • Understand database integration, testing, exception handling, and security.
  • Know how Actuator supports monitoring and why management endpoints need protection.
  • Be able to explain the complete request flow from client to database and back.

31. Conclusion

Spring Boot architecture provides a practical foundation for building maintainable Java applications. Its startup mechanism, auto-configuration, starter dependencies, Spring container, and embedded server reduce repetitive setup work. A layered design separates request handling, business logic, and data access, making applications easier to test and extend.

Understanding these architectural components is important before developing more advanced features such as REST APIs, database transactions, authentication, server-side validation, and microservices.

Learn more through the Advanced Java Training Course at JustAcademy, register for a course demo, or visit the JustAcademy homepage.

32. Additional Learning Resources

Previous Next
whatsapp